package com.mh.dto.bo;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mh.dto.vo.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Date:2024/11/14
 * author:zmh
 * description: 用户管理器单例对象
 **/

@Data
@Component
@Slf4j
public class UserManager {
    // 管理连接用户信息
    private final HashMap<String, Room> roomMap = new HashMap<>();
    private final HashMap<String, ConnectionInfo>userMap = new HashMap<>();
    private final HashMap<WebSocketSession, String>wsMap = new HashMap<>();
    // 创建房间


    // 加入用户
    public void addUser(String roomId, String userId, WebSocketSession session) {
        Room room = roomMap.get(roomId);
        if (room == null) {
            room = new Room(){};
        }
        WsSession wsSession = new WsSession(){};
        wsSession.setSession(session);
        wsSession.setUserId(userId);
        if (room.getInitiator() != null){
            room.setReceiver(wsSession);
        }else {
            room.setInitiator(wsSession);
        }

        ConnectionInfo ci = new ConnectionInfo(){};
        ci.setRoomId(roomId);
        ci.setSession(session);
        userMap.put(userId, ci);
        roomMap.put(roomId, room);
        wsMap.put(session, roomId);
        log.info("用户{}加入",  userId);
        return;
    }

    // 关闭房间 //通知其他人退出
    public void removeRoom(WebSocketSession session) {
        String roomId  = wsMap.get(session);
        Room room = roomMap.get(roomId);
        if (room == null)return;
        WsSession receiver = room.getReceiver();
        WsSession initiator = room.getInitiator();
        if (receiver != null){
            String receiverId = receiver.getUserId();
            ConnectionInfo connectionInfo = userMap.get(receiverId);
            MessageReceive messageReceive = new MessageReceive() {
            };
            messageReceive.setUserId(receiverId);
            messageReceive.setType("leave");
            if (connectionInfo != null && !userMap.get(receiverId).getSession().equals(session)){
                this.sendMessage(messageReceive);
            }
            wsMap.remove(receiver.getSession());
            userMap.remove(receiverId);
        }
        if (initiator != null){
            String initiatorId = initiator.getUserId();
            ConnectionInfo connectionInfo = userMap.get(initiatorId);
            MessageReceive messageReceive = new MessageReceive() {
            };
            messageReceive.setUserId(initiatorId);
            messageReceive.setType("leave");
            if (connectionInfo != null && !userMap.get(initiatorId).getSession().equals(session)){
                this.sendMessage(messageReceive);
            }
            wsMap.remove(initiator.getSession());
            userMap.remove(initiatorId);
        }
        roomMap.remove(roomId);

        log.info("房间{}关闭", roomId);
    }

    // 获取用户
    public WebSocketSession getUser(String userId) {
        ConnectionInfo ci = userMap.get(userId);
        if (ci != null){
            return ci.getSession();
        }
        return null;
    }

    // 获取所有用户ID构造成list返回
    public List<String> getAllUserId() {
        return userMap.keySet().stream().collect(Collectors.toList());
    }

    // 通知用户加入-广播消息
    public void sendMessageAllUser() throws IOException {
        // 获取所有连接用户ID列表
        List<String> allUserId = getAllUserId();
        for (String userId : userMap.keySet()) {
            ConnectionInfo ci = userMap.get(userId);
            MessageOut messageOut = new MessageOut("join", allUserId);
            String messageText = new ObjectMapper().writeValueAsString(messageOut);
            // 广播消息
             ci.getSession().sendMessage(new TextMessage(messageText));
        }
    }

    // 给指定用户发送特定类型消息
    public void sendMessage(MessageReceive messageReceive){
        String userId = messageReceive.getUserId();
        String type = messageReceive.getType();
        Object data = messageReceive.getData();
        WebSocketSession session = getUser(userId);
        try {
            MessageOut messageOut = new MessageOut(type, data);
            String messageText = new ObjectMapper().writeValueAsString(messageOut);
            session.sendMessage(new TextMessage(messageText));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
